package com.example.demo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.anno.AutoCustomAnnotation;
import com.example.demo.entity.UsersInfo;
import com.example.demo.entity.dto.UserLoginDTO2;
import com.example.demo.error.costom.PasswordException;
import com.example.demo.error.costom.PhoneNumberAlreadyExistsException;
import com.example.demo.mapper.UsersInfoMapper;
import com.example.demo.result.Result;
import com.example.demo.service.IUsersInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户信息 服务实现类
 * </p>
 *
 * @author Mr.Abel
 * @since 2024-03-13
 */
@Slf4j
@Service
public class UsersInfoServiceImpl extends ServiceImpl<UsersInfoMapper, UsersInfo> implements IUsersInfoService {


    /**
     * 注册用户信息。
     *
     * @param usersInfo 包含用户信息的对象，主要有用户名（手机号）、密码和盐值。
     *                  该方法会检查手机号是否已存在，若存在则抛出异常。
     *                  对密码进行MD5加密并添加盐值，然后保存用户信息。
     * @throws PhoneNumberAlreadyExistsException 如果手机号已经存在，则抛出此异常。
     */
    @Override
    public void register(UsersInfo usersInfo) {
        // 查询数据库中是否存在相同的手机号
        QueryWrapper<UsersInfo> queryWrapper = new QueryWrapper<UsersInfo>()
                .eq("phone", usersInfo.getPhone());
        UsersInfo usersInfo1 = getOne(queryWrapper);
        // 如果查询结果不为空，表示手机号已存在，抛出异常
        if(usersInfo1!=null){
            throw new PhoneNumberAlreadyExistsException();
        }
        // 使用MD5算法对密码进行加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        // 生成随机的盐值
        String salt = IdUtil.simpleUUID().substring(0,20);
        md5.setSalt(salt.getBytes());
        // 加盐后加密密码
        String md5Pass = md5.digestHex(usersInfo.getPassword());
        usersInfo.setPassword(md5Pass);
        // 设置用户信息中的盐值
        usersInfo.setSalt(salt);
        // 使用手机号作为用户名
        usersInfo.setUsername(usersInfo.getPhone());
        // 保存用户信息到数据库
        this.save(usersInfo);
    }




    @Override
    public UserLoginDTO2 login(UsersInfo usersInfo) {
        //查询条件
        QueryWrapper<UsersInfo> queryWrapper = new QueryWrapper<UsersInfo>()
                .eq("username", usersInfo.getUsername());
        UsersInfo usersInfo1 = getOne(queryWrapper);
        if(usersInfo1==null){
            throw new PasswordException();
        }
        //如果有信息查询盐值
        String salt = usersInfo1.getSalt();
        //Md5加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        //（设置盐值）
        md5.setSalt(salt.getBytes());
        //把userinfo拿来加密
        String md5Pass = md5.digestHex(usersInfo.getPassword());
        //判断两个加密后的密码是否一致
        if(!md5Pass.equals(usersInfo1.getPassword())){
            throw new PasswordException();
        }

        UserLoginDTO2 userLoginDTO = new UserLoginDTO2();
        //抹掉密码
        BeanUtil.copyProperties(usersInfo1,userLoginDTO);
        //信息脱敏
        userLoginDTO.setPhone(DesensitizedUtil.mobilePhone(userLoginDTO.getPhone()));
        userLoginDTO.setIdCard(DesensitizedUtil.idCardNum(userLoginDTO.getIdCard(),3,6));
        return userLoginDTO;
    }


    @Override
    public List<UserLoginDTO2> findByPhone(String phone) {
        //通过手机号模糊查询用户然后脱敏转List<DTO>并返回
        //查询条件是模糊查询
        QueryWrapper<UsersInfo> queryWrapper = new QueryWrapper<UsersInfo>()
              .like("phone",phone);
        //查询一个集合
        List<UsersInfo> usersInfos = list(queryWrapper);
        //装备一个list用来保存dto
        ArrayList<UserLoginDTO2> userLoginDTO2s = new ArrayList<>();
        //判断查询数据是否为空
        if(usersInfos!=null){
            //遍历结果
            for(UsersInfo usersInfo:usersInfos){
                //new一个dto
                UserLoginDTO2 userLoginDTO = new UserLoginDTO2();
                //entity转dto
                BeanUtil.copyProperties(usersInfo,userLoginDTO);
                //脱敏
                userLoginDTO.setPhone(DesensitizedUtil.mobilePhone(userLoginDTO.getPhone()));
                userLoginDTO.setIdCard(DesensitizedUtil.idCardNum(userLoginDTO.getIdCard(),3,6));
                //dto放入集合
                userLoginDTO2s.add(userLoginDTO);
            }
        }
        //返回
        return userLoginDTO2s;
    }


    @AutoCustomAnnotation(group = "userinfo:",ttl = 5000)
    @Override
    public UsersInfo selectById(Integer id) {
        return getById(id);
    }


}
